package org

import (
    "time"
	"strings"
	"strconv"
	"wxsdk/oauth"
	"encoding/json"
	"dhfshop/models/org"
	"dhfshop/models/misc"
	"dhfshop/utils/helper"
	"dhfshop/service/redisgo"
	"dhfshop/controllers/base"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/validation"
	jwt "github.com/dgrijalva/jwt-go"
	"dhfshop/service/wechat"
	"github.com/skip2/go-qrcode"
	"encoding/base64"
	"dhfshop/domain/nsqproc"
)

type WebLoginController struct {
	base.BaseController
}

// web登陆API
func (this *WebLoginController) WebLogin() {
    var (
		curPartnerId int64 = 0
		curSubRoleId int64 = 0
		curUserId    int64 = 0
		isDealer     int   = 0
	)
	v := struct {
	    Code           string   `form:"code" valid:"Required"`
		EncryptedData  string   `form:"encryptedData" valid:"Required"`
		Iv             string   `form:"iv" valid:"Required"`
		IdentityId     string   `form:"identity_id"`
		PartnerId      int64    `form:"partner_id"`
		DhfXid         string   `form:"dhfxid"`
		RefUserId      int64    `form:"ref_user_id"`
	}{} 
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return 
	}
	appId := beego.AppConfig.String("SellerAppID")
	appSecret := beego.AppConfig.String("SellerAppSecret")
	weUser, err := wechat.AppletSellerLogin(appId, appSecret, v.Code, v.EncryptedData, v.Iv)
	if err != nil{
		this.ServeError(err.Error())
		return
	}
	// 第一次登录
	if v.PartnerId == 0 {
	    //系统存在用户ID
		if user, err := org.GetUserIdByOpenId(weUser.OpenID); err == nil {
			user.Avatar = weUser.AvatarURL
			user.SessionKey = weUser.SessionKey
			org.UpdateUsersById(user, "avatar", "session_key")    //更新:avatar,session_key
			//屏蔽对手
			if !user.Activated {
				this.ServeError("用户已经停用,请联系管理员")
				return 
			}
			//
			if ok := strings.Contains(user.RoleIds, ","); ok {
				partnerIdNameArr := make(map[string]string) 
				for _, roleIdStr := range strings.Split(user.RoleIds, ",") {
					roleId, _:= strconv.ParseInt(roleIdStr, 10, 64)
					if role, err := org.GetPartnerIdByRoleId(roleId); err == nil {
						if partner, err := org.GetPartnerById(role.PartnerId); err == nil {
						    partnerIdNameArr[strconv.FormatInt(role.PartnerId, 10)] = partner.Name
						}	
					}
				}
				partnerIdArr := []string{}
				for key, _ := range partnerIdNameArr {
					partnerIdArr = append(partnerIdArr, key)
				}
				rsp := struct {
					OpenId          string            `json:"open_id"`
					PartnerIds      string            `json:"partner_ids"`
					PartnerIdNames  map[string]string `json:"partner_id_names"`
				}{OpenId: weUser.OpenID, PartnerIds: strings.Join(partnerIdArr, ","), PartnerIdNames: partnerIdNameArr}
				this.Data["json"] = rsp
				this.ServeJSON()
				return
			}else{
				curSubRoleId, _= strconv.ParseInt(user.RoleIds, 10, 64)
				if role, err := org.GetPartnerIdByRoleId(curSubRoleId); err == nil {
					curPartnerId = role.PartnerId
					curUserId = user.UserId
					if len(role.DataRange) > 5 {
						if _,_,partByUser,err := helper.JsonToDataRangeStr(role.DataRange,0);err == nil && partByUser{
						    isDealer = 1
						}
					}
				}
			}
		}else{      //注册用户
			partner := org.ValuePartner{Activated:true}
			partner.PartnerId, _ = misc.GetCompanyNo()
			partner.ServeStartAt = time.Now().UTC()
			partner.ServeEndAt = partner.ServeStartAt.Add(30*24*time.Hour)
			partner.OrderVersion = "9"  //默认是体验版
			if _, err = org.AddPartner(&partner); err != nil {
				this.ServeError(err.Error())
				return
			}
			roleId, err := org.InitDefaultPartnerData(partner.PartnerId)
			if err != nil {
				this.ServeError(err.Error())
				return
			}
			user, err := org.CreateWeChatUser(0,strconv.FormatInt(roleId, 10),&weUser,v.RefUserId)
			if err != nil {
				this.ServeError(err.Error())
				return
			}
			curPartnerId = partner.PartnerId
			curSubRoleId = roleId
			curUserId = user.UserId
			if role, err := org.GetPartnerIdByRoleId(curSubRoleId); err == nil {
				if len(role.DataRange) > 5 {
					if _,_,partByUser,err := helper.JsonToDataRangeStr(role.DataRange,0);err == nil && partByUser{
						isDealer = 1
					}
				}
			}
			partner.CreatorId = curUserId
			if err := org.UpdatePartnerById(&partner, "creator_id"); err != nil{
				this.ServeError(err.Error())
				return
			}
		}
	}else{   //第二次登录
		user, err := org.GetUserIdByOpenId(weUser.OpenID)
		if err != nil {
		    this.ServeError("open_id is invalid")
			return
		}
		// 屏蔽对手
		if !user.Activated {
		    this.ServeError("用户已经停用,请联系管理员")
		    return 
		}
		//
		user.SessionKey = weUser.SessionKey
		org.UpdateUsersById(user, "session_key")    //更新:session_key
		for _, roleIdStr := range strings.Split(user.RoleIds, ",") {
			roleId, _:= strconv.ParseInt(roleIdStr, 10, 64)
			if role, err := org.GetPartnerIdByRoleId(roleId); err == nil {
				if v.PartnerId == role.PartnerId {
					curPartnerId = role.PartnerId
					curSubRoleId = roleId
					curUserId = user.UserId
					if len(role.DataRange) > 5 {
						if _,_,partByUser,err := helper.JsonToDataRangeStr(role.DataRange,0);err == nil && partByUser{
						    isDealer = 1
						}
					}
					break
				}
			}
		}
		if curPartnerId == 0 {
			this.ServeError("partner_id is invalid")
			return
		}
	}
	//验证订购时间
	/*
	if partner, err := org.GetPartnerById(curPartnerId); err == nil {
		if time.Now().UTC().Unix() >= partner.ServeEndAt.Unix() {
		    this.ServeError("订购过期")
		    return
		}
	}
	*/
	nsqproc.CreateLoinInitTask(curPartnerId)
	/********create token************/
	token := jwt.New(jwt.GetSigningMethod("HS256"))
	claims := token.Claims.(jwt.MapClaims)
	claims["CurrentUser"] = struct {
	    Id        int
		CompanyId int
		Role      int
		SubRoleId int
		DhfxId    string
        IsDealer  int		
	}{Id:int(curUserId),CompanyId:int(curPartnerId),Role:2,SubRoleId:int(curSubRoleId),DhfxId:v.DhfXid,IsDealer:isDealer}
	claims["exp"] = time.Now().UTC().Add(time.Hour * 24 * 1).Unix()
	tokenSecret := beego.AppConfig.String("AuthTokenSecret")
	tokenString, err := token.SignedString([]byte(tokenSecret))
	if err != nil {
		this.ServeError("登录失败，请稍后再试")
		return
	}
	if len(v.IdentityId) > 0 {
	    // 缓存identity_id和token对应关系
		redisconn := redisgo.GetInstance()
		if ok, _:= redisconn.Exists(v.IdentityId); ok {
			redisconn.Del(v.IdentityId)  
		}
		tokenCacheMap := make(map[string]string) 
		tokenCacheMap["token"] = tokenString
		tokenCacheMap["open_id"] = weUser.OpenID
	    tokenJSON, err := json.Marshal(tokenCacheMap)
		if err != nil {
		    this.ServeError(err.Error())
		    return
	    }
		if _, err = redisconn.Set(v.IdentityId, string(tokenJSON), 5*60); err != nil {
			beego.Debug("SETEX", err.Error())
		}
	}
	//TimerProSvr.timerMsgDao <- &TimerReqDao{Types:types, CallBack:callBackData}
	this.Data["json"] = map[string]string{
	    "open_id": weUser.OpenID,
		"token": tokenString,
	}
	this.ServeJSON()
}

func (this *WebLoginController) NewWebLogin() {
    var (
		curPartnerId   int64 = 0
		curPartnerName string
		curSubRoleId   int64 = 0
		curUserId      int64 = 0
		isDealer       int   = 0
		err            error
	)
	v := struct {
	    Code           string   `form:"code" valid:"Required"`
		IdentityId     string   `form:"identity_id"`
		PartnerId      int64    `form:"partner_id"`
		DhfXid         string   `form:"dhfxid"`
		RefUserId      int64    `form:"ref_user_id"`
	}{} 
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return 
	}
	appId := beego.AppConfig.String("SellerAppID")
	appSecret := beego.AppConfig.String("SellerAppSecret")
	basicUser := new(oauth.SessionInfo)
	basicUser, err = oauth.JsCode2SessionOwn(appId, appSecret, v.Code)
	if err != nil {
	    beego.Debug(err.Error())
		return
	}
	// 第一次登录
	if v.PartnerId == 0 {
	    //系统存在用户ID
		if user, err := org.GetUserIdByOpenId(basicUser.OpenId); err == nil {
			user.SessionKey = basicUser.SessionKey
			org.UpdateUsersById(user, "session_key")    //更新:avatar,session_key
			//屏蔽对手
			if !user.Activated {
				this.ServeError("用户已经停用,请联系管理员")
				return 
			}
			//
			if ok := strings.Contains(user.RoleIds, ","); ok {
				partnerIdNameArr := make(map[string]string) 
				for _, roleIdStr := range strings.Split(user.RoleIds, ",") {
					roleId, _:= strconv.ParseInt(roleIdStr, 10, 64)
					if role, err := org.GetPartnerIdByRoleId(roleId); err == nil {
						if partner, err := org.GetPartnerById(role.PartnerId); err == nil {
						    partnerIdNameArr[strconv.FormatInt(role.PartnerId, 10)] = partner.Name
						}	
					}
				}
				partnerIdArr := []string{}
				for key, _ := range partnerIdNameArr {
					partnerIdArr = append(partnerIdArr, key)
				}
				rsp := struct {
					OpenId          string            `json:"open_id"`
					PartnerIds      string            `json:"partner_ids"`
					PartnerIdNames  map[string]string `json:"partner_id_names"`
				}{OpenId: basicUser.OpenId, PartnerIds: strings.Join(partnerIdArr, ","), PartnerIdNames: partnerIdNameArr}
				this.Data["json"] = rsp
				this.ServeJSON()
				return
			}else{
				curSubRoleId, _= strconv.ParseInt(user.RoleIds, 10, 64)
				if role, err := org.GetPartnerIdByRoleId(curSubRoleId); err == nil {
					curPartnerId = role.PartnerId
					curUserId = user.UserId
					if len(role.DataRange) > 5 {
						if _,_,partByUser,err := helper.JsonToDataRangeStr(role.DataRange,0);err == nil && partByUser{
						    isDealer = 1
						}
					}
				}
			}
		}else{      //注册用户
			partner := org.ValuePartner{Activated:true}
			partner.PartnerId, _ = misc.GetCompanyNo()
			partner.ServeStartAt = time.Now().UTC()
			partner.ServeEndAt = partner.ServeStartAt.Add(30*24*time.Hour)
			partner.OrderVersion = "9"  //默认是体验版
			if _, err = org.AddPartner(&partner); err != nil {
				this.ServeError(err.Error())
				return
			}
			roleId, err := org.InitDefaultPartnerData(partner.PartnerId)
			if err != nil {
				this.ServeError(err.Error())
				return
			}
			user, err := org.CreateBasicWeChatUser(0,appId,strconv.FormatInt(roleId, 10),basicUser,v.RefUserId)
			if err != nil {
				this.ServeError(err.Error())
				return
			}
			curPartnerId = partner.PartnerId
			curSubRoleId = roleId
			curUserId = user.UserId
			if role, err := org.GetPartnerIdByRoleId(curSubRoleId); err == nil {
				if len(role.DataRange) > 5 {
					if _,_,partByUser,err := helper.JsonToDataRangeStr(role.DataRange,0);err == nil && partByUser{
						isDealer = 1
					}
				}
			}
			partner.CreatorId = curUserId
			if err := org.UpdatePartnerById(&partner, "creator_id"); err != nil{
				this.ServeError(err.Error())
				return
			}
		}
	}else{   //第二次登录
		user, err := org.GetUserIdByOpenId(basicUser.OpenId)
		if err != nil {
		    this.ServeError("open_id is invalid")
			return
		}
		// 屏蔽对手
		if !user.Activated {
		    this.ServeError("用户已经停用,请联系管理员")
		    return 
		}
		//
		user.SessionKey = basicUser.SessionKey
		org.UpdateUsersById(user, "session_key")    //更新:session_key
		for _, roleIdStr := range strings.Split(user.RoleIds, ",") {
			roleId, _:= strconv.ParseInt(roleIdStr, 10, 64)
			if role, err := org.GetPartnerIdByRoleId(roleId); err == nil {
				if v.PartnerId == role.PartnerId {
					curPartnerId = role.PartnerId
					curSubRoleId = roleId
					curUserId = user.UserId
					if len(role.DataRange) > 5 {
						if _,_,partByUser,err := helper.JsonToDataRangeStr(role.DataRange,0);err == nil && partByUser{
						    isDealer = 1
						}
					}
					break
				}
			}
		}
		if curPartnerId == 0 {
			this.ServeError("partner_id is invalid")
			return
		}
	}
	//验证订购时间
	/*
	if partner, err := org.GetPartnerById(curPartnerId); err == nil {
		if time.Now().UTC().Unix() >= partner.ServeEndAt.Unix() {
		    this.ServeError("订购过期")
		    return
		}
	}
	*/
	nsqproc.CreateLoinInitTask(curPartnerId)
	/********create token************/
	token := jwt.New(jwt.GetSigningMethod("HS256"))
	claims := token.Claims.(jwt.MapClaims)
	claims["CurrentUser"] = struct {
	    Id        int
		CompanyId int
		Role      int
		SubRoleId int
		DhfxId    string
        IsDealer  int		
	}{Id:int(curUserId),CompanyId:int(curPartnerId),Role:2,SubRoleId:int(curSubRoleId),DhfxId:v.DhfXid,IsDealer:isDealer}
	claims["exp"] = time.Now().UTC().Add(time.Hour * 24 * 1).Unix()
	tokenSecret := beego.AppConfig.String("AuthTokenSecret")
	tokenString, err := token.SignedString([]byte(tokenSecret))
	if err != nil {
		this.ServeError("登录失败，请稍后再试")
		return
	}
	if len(v.IdentityId) > 0 {
	    // 缓存identity_id和token对应关系
		redisconn := redisgo.GetInstance()
		if ok, _:= redisconn.Exists(v.IdentityId); ok {
			redisconn.Del(v.IdentityId)  
		}
		tokenCacheMap := make(map[string]string) 
		tokenCacheMap["token"] = tokenString
		tokenCacheMap["open_id"] = basicUser.OpenId
	    tokenJSON, err := json.Marshal(tokenCacheMap)
		if err != nil {
		    this.ServeError(err.Error())
		    return
	    }
		if _, err = redisconn.Set(v.IdentityId, string(tokenJSON), 5*60); err != nil {
			beego.Debug("SETEX", err.Error())
		}
	}
	//TimerProSvr.timerMsgDao <- &TimerReqDao{Types:types, CallBack:callBackData}
	if partner, err := org.GetPartnerById(curPartnerId); err == nil {
	   curPartnerName = partner.Name
	}
	this.Data["json"] = map[string]string{
	    "open_id": basicUser.OpenId,
		"token": tokenString,
		"partner_id": strconv.FormatInt(curPartnerId, 10),
		"partner_name": curPartnerName,
	}
	this.ServeJSON()
}

func (this *WebLoginController) TokenGet() {
    v := struct {
		IdentityId     string   `form:"identity_id" valid:"Required"`
	}{} 
	this.ParseForm(&v)
	valid := validation.Validation{}
	passed, _ := valid.Valid(&v)
	if !passed {
		this.ServeError(valid.Errors[0].Key+" "+valid.Errors[0].Message)
		return 
	}
	redisconn := redisgo.GetInstance()
	if ok, _:= redisconn.Exists(v.IdentityId); !ok {
		this.ServeError("identity_id is invalid or expired")
		return   
	}
	tokenCacheMap := map[string]string{}
	if cacheValue, err := redisconn.GetString(v.IdentityId); err == nil && len(cacheValue) > 20  {
		if err = json.Unmarshal([]byte(cacheValue), &tokenCacheMap); err != nil {
			this.ServeError(err.Error())
		    return
		}
	}else{
        this.ServeError(err.Error())
		return
    }
	redisconn.Del(v.IdentityId)  //请求一次就删除  
	this.Data["json"] = map[string]string{
		"token": tokenCacheMap["token"],
		"open_id": tokenCacheMap["open_id"],
	}
	this.ServeJSON()
}

func (this *WebLoginController) QrCodeGet() {
	base64Flag := false
	code := this.GetString("code")
	if code == "" {
	    this.ServeError("code value is null")
	    return
	}
	base64Flag, _= this.GetBool("base64")
	data, err := qrcode.Encode(code,qrcode.Medium,256)
	if err != nil{
		this.ServeError(err.Error())
	    return
	}
	if base64Flag {
	    encodeString := base64.StdEncoding.EncodeToString(data)
	    this.Ctx.ResponseWriter.Write([]byte(encodeString))
	    return
	}
	this.Ctx.ResponseWriter.Write(data)
}
